﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Data.SqlClient;
using System.Threading;

namespace MoonLight.LibCommon
{
    public class Logger
    {
        public static void SetLogPath()
        {
            string log_dir = Environment.CurrentDirectory + @"\Logs";
            
            if (!Directory.Exists(log_dir))
            {
                Directory.CreateDirectory(log_dir);
            }
            m_path = log_dir + @"\trace.log";
        }

        public static void SetLogPath(string path_dir)
        {
            string log_dir = path_dir + @"\Logs";

            if (!Directory.Exists(log_dir))
            {
                Directory.CreateDirectory(log_dir);
            }
            m_path = log_dir + @"\trace.log";
        }

        public static void CloseLog()
        {
            if (m_fs != null) {
                m_fs.Close();
            }
        }

        public static int WriteSqlConsole(string sql, List<SqlParameter> para_list)
        {
            if (para_list == null || para_list.Count == 0)
            {
                Logger.WriteConsole(sql);
                return 0;
            }

            for (int i = 0; i < para_list.Count; i++)
            {
                sql = sql.Replace(para_list[i].ParameterName, para_list[i].Value.ToString());
            }
            Console.WriteLine(sql);
            return 0;
        }

        public static int WriteConsole(string logstr)
        {
            Console.WriteLine(logstr);
            return 0;
        }

        public static int WriteSqlLog(string sql, List<SqlParameter> para_list)
        {
            if (before_write() < 0)
                return -1;

            if (para_list != null && para_list.Count > 0)
            {
                for (int i = 0; i < para_list.Count; i++)
                {
                    sql = sql.Replace(para_list[i].ParameterName, para_list[i].Value.ToString());
                }
            }
            format_logstr(sql, CommonDefine.LogLevel_e.INFO);
            return write_log();
        }

        public static int WriteLog(string logstr)
        {
            if (before_write() < 0)
                return -1;
            format_logstr(logstr, CommonDefine.LogLevel_e.INFO);
            return write_log();
        }

        public static int WriteLogWarn(string logstr)
        {
            if (before_write() < 0)
                return -1;
            format_logstr(logstr, CommonDefine.LogLevel_e.WARN);
            return write_log();
        }

        public static int WriteLogError(string logstr)
        {
            if (before_write() < 0)
                return -1;
            format_logstr(logstr, CommonDefine.LogLevel_e.ERROR);
            return write_log();
        }

        private static int before_write()
        {
            if (!File.Exists(m_path))
            {
                try
                {
                    FileStream fs = File.Create(m_path);
                    fs.Close();
                }
                catch (Exception ex)
                {
                    Logger.WriteConsole(ex.Message);
                    return -1;
                }
            }

            FileInfo info = new FileInfo(m_path);
            if (info.Length > 1024 * 1024 * 10)
            {
                try
                {
                    string path = m_path + DateTime.Now.Year + "_" + DateTime.Now.Month + "_" + DateTime.Now.Day + "_" + DateTime.Now.Hour + "_" + DateTime.Now.Minute + "_" + DateTime.Now.Second;
                    info.MoveTo(path);
                }
                catch (Exception ex)
                {
                    Logger.WriteConsole(ex.Message);
                    return -1;
                }
            }
            return 0;
        }

        private static void format_logstr(string logstr, CommonDefine.LogLevel_e level)
        {
            StackFrame sf = new StackFrame(2, true);
            string full_name = sf.GetFileName();
            if (full_name != null)
            {
                string name = full_name.Substring(full_name.LastIndexOf("\\") + 1);
                switch (level)
                {
                    case CommonDefine.LogLevel_e.INFO:
                        m_logstr = "[" + DateTime.Now.ToString() + "][" + name + "][" + sf.GetMethod().Name + "][" + sf.GetFileLineNumber() + "][INFO]" + logstr + "\r\n";
                        break;
                    case CommonDefine.LogLevel_e.WARN:
                        m_logstr = "[" + DateTime.Now.ToString() + "][" + name + "][" + sf.GetMethod().Name + "][" + sf.GetFileLineNumber() + "][WARN]" + logstr + "\r\n";
                        break;
                    case CommonDefine.LogLevel_e.ERROR:
                        m_logstr = "[" + DateTime.Now.ToString() + "][" + name + "][" + sf.GetMethod().Name + "][" + sf.GetFileLineNumber() + "][ERROR]" + logstr + "\r\n";
                        break;
                    default:
                        break;
                }
            }
            else
            {
                switch (level)
                {
                    case CommonDefine.LogLevel_e.INFO:
                        m_logstr = "MoonLight:[INFO]" + logstr + "\r\n";
                        break;
                    case CommonDefine.LogLevel_e.WARN:
                        m_logstr = "MoonLight:[WARN]" + logstr + "\r\n";
                        break;
                    case CommonDefine.LogLevel_e.ERROR:
                        m_logstr = "MoonLight:[ERROR]" + logstr + "\r\n";
                        break;
                    default:
                        break;
                }
            }
        }

        private static int write_log()
        {
            m_mtx.WaitOne();
            int result = 0;
            m_fs = null;
            try
            {
                byte[] bytes = Encoding.Default.GetBytes(m_logstr);
                m_fs = new FileStream(m_path, FileMode.Append, FileAccess.Write);
                m_fs.Write(bytes, 0, bytes.Length);
                m_fs.Flush();
            }
            catch (Exception ex)
            {
                Logger.WriteConsole(Thread.CurrentThread.ManagedThreadId + " " + ex.Message);
                result = -1;
            }
            if (m_fs != null)
                m_fs.Close();
            m_mtx.ReleaseMutex();
            return result;
        }

        private static string m_path = "";
        private static string m_logstr = "";
        private static Mutex m_mtx = new Mutex(false);
        private static FileStream m_fs;
    }
}
